home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2000 #4
/
Amiga Plus CD - 2000 - No. 4.iso
/
Tools
/
Emulatoren
/
UAE0.6.4
/
src
/
bebox.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-05-27
|
18KB
|
840 lines
/*
* UAE - The Un*x Amiga Emulator
*
* BeBox port specific stuff
*
* (c) 1996 Christian Bauer
* (c) 1996 Patrick Hanevold
*/
#define VersionStr "0.6.4"
#include <AppKit.h>
#include <InterfaceKit.h>
#include <KernelKit.h>
#include <Record.h>
#include <File.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define __STDC__ 1
#define __GNU_LIBRARY__
#include <getopt.h>
#undef __GNU_LIBRARY__
#undef __STDC__
#ifndef __bebox__
#error Compiling bebox.cpp, but __bebox__ unset.
#endif
#include "bebox.h"
extern void deinit_sound(void);
/*
* Create application object and start it
*/
UAE *the_app;
main()
{
the_app = new UAE();
the_app->Run();
delete the_app;
return 0;
}
/*
* UAE Constructor: Initialize member variables
*/
UAE::UAE() : BApplication('UAEm')
{
the_bitmap = NULL;
the_emulator = NULL;
main_window = NULL;
window_open = FALSE;
// Init Key events
CurentEvent = (Event*)malloc(sizeof(Event));
LastEvent=CurentEvent;
CurentEvent->Age=0;
CurentEvent->Next=0;
}
void UAE::ArgvReceived(int argc, char **argv)
{
parse_cmdline(argc,argv);
}
/*
* Arguments processed, create and start emulation
*/
void UAE::ReadyToRun(void)
{
vsize = correct_aspect ? 2*numscrlines : numscrlines;
hsize = use_lores ? 400 : 800;
hpixels = use_lores ? 320 : 796;
// Allocate bitmap
the_bitmap = new BBitmap(BRect(0, 0, hsize-1, vsize-1), B_COLOR_8_BIT);
// Set up vidinfo
gfxvidinfo.bufmem = (char *)the_bitmap->Bits();
gfxvidinfo.rowbytes = the_bitmap->BytesPerRow();
gfxvidinfo.pixbytes = 1;
gfxvidinfo.maxblocklines = 100;
gfxvidinfo.maxlinetoscr = 0;
gfxvidinfo.x_adjust = 0;
gfxvidinfo.maxline = 100000; /* ??? */
// Open window
main_window = new UAEWindow(BRect(0, 0, hpixels-1, vsize+B_MENU_BAR_HEIGHT), the_bitmap);
// Initialize mouse and keyboard variables
buttonstate[0] = buttonstate[1] = buttonstate[2] = FALSE;
lastmx = lastmy = 0;
newmousecounters = FALSE;
inwindow = TRUE;
// Start emulation
the_emulator = new Emulator;
the_emulator->Run();
}
/*
* Quit requested (either by menu or by closing the window)
*/
bool UAE::QuitRequested(void)
{
if (BApplication::QuitRequested()) {
// Stop emulation
if (the_emulator) {
the_emulator->Quit();
delete the_emulator;
}
// Deallocate bitmap
if (the_bitmap)
delete the_bitmap;
return TRUE;
}
return FALSE;
}
/*
* Display "about" window
*/
void UAE::AboutRequested(void)
{
char str[256];
sprintf(str, " Un*x Amiga Emulator V"VersionStr"\n"
" by Bernd Schmidt\n"
" BeBox port by Christian Bauer\n"
"Additional porting by Patrick Hanevold");
BAlert *the_alert = new BAlert("", str, "OK");
the_alert->Go();
}
//void UAE::MessageReceived(BMessage *Msg)
//{
// switch(Msg->what)
// {
// default:
// BApplication::MessageReceived(Msg);
// }
//}
char *DiskName[4];
char *FileName[4];
int FloppyN;
void UAE::RefsReceived(BMessage *Msg)
{
ulong type;
long count;
BFile *File;
BDirectory *dir,*dir2;
char FileNm[256]; // = (char*)Msg->FindString("filename");
char Path1[512]="";
char Path2[512]="";
int err;
Msg->GetInfo("refs",&type,&count);
for(long n=--count;n>=0;n--){
record_ref item = Msg->FindRef("refs",n);
if(item.database>=0 && item.record>=0){
if(does_ref_conform(item,"File")){
File = new BFile;
File->SetRef(item);
File->GetName(FileNm);
DiskName[FloppyN]=FileNm;
File->GetName(Path2);
dir = new BDirectory;
dir2 = new BDirectory;
err = File->GetParent(dir);
while(err == B_NO_ERROR)
{
dir->GetName(Path1);
if(strlen(Path2))
{
strcat(Path1,"/");
strcat(Path1,Path2);
}
strcpy(Path2,Path1);
err = dir->GetParent(dir2);
if(err==B_NO_ERROR) dir->SetRef(dir2->Record()->Ref());
}
strcpy(Path1,"/");
strcat(Path1,Path2);
// strcpy(FileName[FloppyN],Path1);
FileName[FloppyN]=Path1;
disk_eject(FloppyN);
disk_insert(FloppyN,Path1);
delete(dir);
delete(dir2);
delete(File);
}
//else BRecord *rec = new BRecord(item);
}
}
}
void UAE::FilePanelClosed(BMessage *Msg)
{
}
void UAE::RequestFile(char *Title,int Drive)
{
FloppyN=Drive;
RunFilePanel(Title,"Insert","Eject",FALSE,NULL);
}
/*
* UAE Window constructor
*/
LEDView *PowerLED,*DriveLED;
#define M_DF0 'MDF0'
#define M_DF1 'MDF1'
#define M_DF2 'MDF2'
#define M_DF3 'MDF3'
#define M_FR1 'MFR1'
#define M_FR2 'MFR2'
#define M_FR3 'MFR3'
#define M_FR4 'MFR4'
#define M_FR5 'MFR5'
#define M_FR6 'MFR6'
#define M_FR7 'MFR7'
UAEWindow::UAEWindow(BRect frame, BBitmap *bitmap) : BWindow(frame,"UAE "VersionStr, B_TITLED_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE)
{
BRect MenuRect = Bounds();
BRect PowerRect = Bounds();
BRect DriveRect = Bounds();
BRect MeterRect = Bounds();
MenuRect.bottom = MenuRect.top + B_MENU_BAR_HEIGHT;
MenuRect.right -= 8;
DriveRect.bottom = MenuRect.bottom;
DriveRect.left = MenuRect.right+1;
DriveRect.right = DriveRect.left+3;
PowerRect.bottom = MenuRect.bottom;
PowerRect.left = DriveRect.right+1;
PowerRect.right = PowerRect.left+3;
MeterRect.left += 50;
MeterRect.right -= 15;
MeterRect.top += 5;
MeterRect.bottom = B_MENU_BAR_HEIGHT-5;
BView *DriveView = new BView(DriveRect,"",B_FOLLOW_NONE, B_WILL_DRAW);
BMenuBar *MenuBar = new BMenuBar(MenuRect,"MenuBar",B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP, B_ITEMS_IN_ROW, FALSE);
BMenu *Menu;
BMenu *SubMenu;
BMenuItem *DriveItem[4],*RateItem[7];
DiskName[0]=df0;
DiskName[1]=df1;
DiskName[2]=df2;
DiskName[3]=df3;
Menu = new BMenu("Amiga", B_ITEMS_IN_COLUMN); MenuBar->AddItem(Menu);
SubMenu = new BMenu("Floppy", B_ITEMS_IN_COLUMN); Menu->AddItem(SubMenu);
DriveItem[0] = new BMenuItem(DiskName[0], new BMessage(M_DF0), NULL); SubMenu->AddItem(DriveItem[0]);
DriveItem[1] = new BMenuItem(DiskName[1], new BMessage(M_DF1), NULL); SubMenu->AddItem(DriveItem[1]);
DriveItem[2] = new BMenuItem(DiskName[2], new BMessage(M_DF2), NULL); SubMenu->AddItem(DriveItem[2]);
DriveItem[3] = new BMenuItem(DiskName[3], new BMessage(M_DF3), NULL); SubMenu->AddItem(DriveItem[3]);
SubMenu = new BMenu("Framerate", B_ITEMS_IN_COLUMN); Menu->AddItem(SubMenu);
SubMenu->SetRadioMode(TRUE);
RateItem[0] = new BMenuItem("1/1", new BMessage(M_FR1), NULL); SubMenu->AddItem(RateItem[0]);
RateItem[1] = new BMenuItem("1/2", new BMessage(M_FR2), NULL); SubMenu->AddItem(RateItem[1]);
RateItem[2] = new BMenuItem("1/3", new BMessage(M_FR3), NULL); SubMenu->AddItem(RateItem[2]);
RateItem[3] = new BMenuItem("1/4", new BMessage(M_FR4), NULL); SubMenu->AddItem(RateItem[3]);
RateItem[4] = new BMenuItem("1/5", new BMessage(M_FR5), NULL); SubMenu->AddItem(RateItem[4]);
RateItem[5] = new BMenuItem("1/6", new BMessage(M_FR6), NULL); SubMenu->AddItem(RateItem[5]);
RateItem[6] = new BMenuItem("1/7", new BMessage(M_FR7), NULL); SubMenu->AddItem(RateItem[6]);
RateItem[3]->SetMarked(TRUE);
AddChild(MenuBar);
// AddChild(DriveView);
// Lock();
// DriveView->SetHighColor(0xff,0,0);
// DriveView->FillRect(DriveRect,B_SOLID_HIGH);
// Unlock();
// SetPulseRate(500000.0/100.0);
DriveLED = new LEDView(DriveRect,0xff,0x80,0,0x80,0x40,0);
AddChild(DriveLED);
PowerLED = new LEDView(PowerRect,0,0xe0,0,0,0xb0,0);
AddChild(PowerLED);
MeterView *Meter = new MeterView(MeterRect);
AddChild(Meter);
int r, g, b, i;
// Move window to right position
MoveTo(80, 60);
// Create bitmap view
Lock();
frame.Set(0,B_MENU_BAR_HEIGHT+1,hsize-1,vsize+B_MENU_BAR_HEIGHT);
main_view = new BitmapView(frame, bitmap);
AddChild(main_view);
main_view->MakeFocus();
main_view->GetKeys(&old_key_info, FALSE);
Unlock();
bitmap_view = main_view;
bitmap_window = this;
// Initialize xcolors
i = 0;
for (r=0; r<16; r++) {
for (g=0; g<16; g++) {
for (b=0; b<16; b++)
xcolors[i++] = index_for_color(r<<4 | r, g<<4 | g, b<<4 | b);
}
}
// Show window
Show();
window_open = TRUE;
}
void UAEWindow::MessageReceived(BMessage *Msg)
{
switch(Msg->what)
{
case M_DF0:
the_app->RequestFile("Insert floppy in DF0:",0);
break;
case M_DF1:
the_app->RequestFile("Insert floppy in DF1:",1);
break;
case M_DF2:
the_app->RequestFile("Insert floppy in DF2:",2);
break;
case M_DF3:
the_app->RequestFile("Insert floppy in DF3:",3);
break;
case M_FR1:
framerate = 1;
break;
case M_FR2:
framerate = 2;
break;
case M_FR3:
framerate = 3;
break;
case M_FR4:
framerate = 4;
break;
case M_FR5:
framerate = 5;
break;
case M_FR6:
framerate = 6;
break;
case M_FR7:
framerate = 7;
break;
default:
printf("Err\n");
BWindow::MessageReceived(Msg);
}
}
/*
* Closing the window quits UAE
*/
bool UAEWindow::QuitRequested(void)
{
window_open = FALSE;
be_app->PostMessage(B_QUIT_REQUESTED);
return TRUE;
}
/*
* Window was (de)activated
*/
void UAEWindow::WindowActivated(bool active)
{
inwindow = active;
}
/*
* Bitmap view constructor
*/
BitmapView::BitmapView(BRect frame, BBitmap *bitmap) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW)
{
the_bitmap = bitmap;
}
/*
* Blit the bitmap
*/
void BitmapView::Draw(BRect update)
{
int xs = use_lores ? prev_max_diwstop - 328 : 0;
BRect from=update;
from.left+=xs;
from.right+=xs;
DrawBitmap(the_bitmap, from, update);
}
void BitmapView::Draw(BRect from, BRect to)
{
DrawBitmap(the_bitmap, from, to);
}
//char KeyState[256];
char RawKeys[128]={
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, AK_BS,AK_TAB,AK_RET,0, 0, 0, 0, 0,
/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AK_ESC, 0, 0, 0, 0,
/* 20 */ AK_SPC,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AK_NPADD, 0, AK_NPSUB,0, 0,
/* 30 */ AK_0, AK_1,AK_2,AK_3,AK_4,AK_5,AK_6,AK_7,AK_8, AK_9, 0, AK_SEMICOLON,0, 0, 0, 0,
/* 40 */ 0, AK_A,AK_B,AK_C,AK_D,AK_E,AK_F,AK_G,AK_H, AK_I, AK_J, AK_K, AK_L, AK_M, AK_N,AK_O,
/* 50 */ AK_P, AK_Q,AK_R,AK_S,AK_T,AK_U,AK_V,AK_W,AK_X, AK_Y, AK_Z, 0, AK_BACKSLASH,0, 0, 0,
/* 60 */ 0, AK_A,AK_B,AK_C,AK_D,AK_E,AK_F,AK_G,AK_H, AK_I, AK_J, AK_K, AK_L, AK_M, AK_N,AK_O,
/* 70 */ AK_P, AK_Q,AK_R,AK_S,AK_T,AK_U,AK_V,AK_W,AK_X, AK_Y, AK_Z, 0, 0, 0, 0, AK_DEL};
void BitmapView::KeyDown(ulong aChar)
{
// printf("$%x\n",aChar);
/*
Event *NewEvent=(Event*)malloc(sizeof(Event));
NewEvent->Next=0;
NewEvent->Age=3;
if((aChar>0x40)&&(aChar<0x5b)){
NewEvent->Key=AK_LSH;
LastEvent->Next=NewEvent;
LastEvent=NewEvent;
NewEvent=(Event*)malloc(sizeof(Event));
NewEvent->Next=0;
NewEvent->Age=3;
NewEvent->Key=RawKeys[aChar];
LastEvent->Next=NewEvent;
LastEvent=NewEvent;
NewEvent=(Event*)malloc(sizeof(Event));
NewEvent->Next=0;
NewEvent->Age=3;
NewEvent->Key=AK_LSH;
}else{
switch(aChar)
{
case 0x3a:
NewEvent->Key=AK_LSH;
LastEvent->Next=NewEvent;
LastEvent=NewEvent;
NewEvent=(Event*)malloc(sizeof(Event));
NewEvent->Next=0;
NewEvent->Age=3;
NewEvent->Key=AK_SEMICOLON;
LastEvent->Next=NewEvent;
LastEvent=NewEvent;
NewEvent=(Event*)malloc(sizeof(Event));
NewEvent->Next=0;
NewEvent->Age=3;
NewEvent->Key=AK_LSH;
break;
default:
NewEvent->Key=RawKeys[aChar];
}
}
LastEvent->Next=NewEvent;
LastEvent=NewEvent;
*/
}
/*
* LED
*/
LEDView::LEDView(BRect frame, int aR, int aG, int aB, int iR, int iG, int iB) : BView(frame,"", B_FOLLOW_NONE, B_WILL_DRAW)
{
ActiveColor.R=aR;
ActiveColor.G=aG;
ActiveColor.B=aB;
IdleColor.R=iR;
IdleColor.G=iG;
IdleColor.B=iB;
State = FALSE;
}
void LEDView::AttachedToWindow(void)
{
bounds = Bounds();
}
void LEDView::Draw(BRect update)
{
Refresh();
}
void LEDView::SetState(bool NewState)
{
if(NewState!=State)
{
State = NewState;
Refresh();
}
}
void LEDView::Refresh(void)
{
Window()->Lock();
if(State) SetHighColor(ActiveColor.R,ActiveColor.G,ActiveColor.B);
else SetHighColor(IdleColor.R,IdleColor.G,IdleColor.B);
FillRect(bounds);
Window()->Unlock();
}
/*
* Meter
*/
MeterView::MeterView(BRect frame) : BView(frame,"", B_FOLLOW_NONE, B_WILL_DRAW|B_PULSE_NEEDED)
{
}
void MeterView::AttachedToWindow(void)
{
bounds = Bounds();
}
void MeterView::Draw(BRect)
{
Refresh();
}
void MeterView::Pulse(void)
{
Refresh();
}
void MeterView::Refresh(void)
{
ulong Speed=frametime/timeframes;
int Frames=Speed/20+1;
BRect Fine=bounds;
Fine.left=Fine.right-(bounds.right-bounds.left)/Frames;
Fine.right=Fine.left+(Speed-20*(Frames-1))*((bounds.right-bounds.left)/Frames)/20;
Window()->Lock();
SetHighColor(0,0,0);
FillRect(bounds);
SetHighColor(255,0,0);
FillRect(Fine);
int R=255-200/Frames;
for(int n=Frames-1; n; n--){
R-=200/Frames;
SetHighColor(R,0,0);
Fine.left=(n-1)*((bounds.right-bounds.left)/Frames);
Fine.right=n*((bounds.right-bounds.left)/Frames);
FillRect(Fine);
}
Window()->Unlock();
}
/*
* Start main emulation thread
*/
void Emulator::Run(void)
{
// Initialize everything
produce_sound = TRUE;
init_sound();
gui_init();
init_joystick();
keybuf_init ();
memory_init();
custom_init();
DISK_init();
init_m68k();
MC68000_reset();
// Start the emulation thread
the_thread = spawn_thread(thread_invoc, "UAE 68000", B_NORMAL_PRIORITY, this);
resume_thread(the_thread);
thread_running = TRUE;
}
/*
* Stop main emulation thread
*/
void Emulator::Quit(void)
{
// Kill the thread if it is running
if (thread_running) {
kill_thread(the_thread);
thread_running = FALSE;
}
close_joystick();
deinit_sound();
}
/*
* The thread's main function
*/
long Emulator::thread_invoc(void *data) //Emulator *obj)
{
Emulator *obj = (Emulator*)data;
obj->thread_func();
return 0;
}
void Emulator::thread_func(void)
{
// This jumps to MC68000_run() and executes the main loop
debug();
thread_running = FALSE;
}
/*
* Redraw a line
*/
void flush_line(int y)
{
if (window_open) {
bitmap_window->Lock();
bitmap_view->Draw(BRect(0, y, hpixels+-1, y));
bitmap_window->Unlock();
}
}
/*
* Redraw a block
*/
void flush_block(int ystart, int ystop)
{
int xs = use_lores ? prev_max_diwstop - 328 : 0;
if (window_open) {
bitmap_window->Lock();
bitmap_view->Draw(BRect(xs, ystart, hpixels+xs-1, ystop), BRect(0, ystart, hpixels-1, ystop));
bitmap_window->Unlock();
}
}
/*
* Redraw the screen
*/
void flush_screen(int ystart, int ystop)
{
}
/*
* Poll mouse and keyboard
*/
void handle_events(void)
{
key_info the_key_info;
int be_code, be_byte, be_bit, amiga_code;
BPoint mouse_point;
ulong mouse_buttons;
// Keyboard
if (window_open && inwindow) {
bitmap_window->Lock();
bitmap_view->GetKeys(&the_key_info, FALSE);
bitmap_window->Unlock();
for (be_code=0; be_code<0x80; be_code++) {
be_byte = be_code >> 3;
be_bit = 1 << (~be_code & 7);
// Key state changed?
if ((the_key_info.key_states[be_byte] & be_bit)
!= (old_key_info.key_states[be_byte] & be_bit)) {
amiga_code = keycode2amiga[be_code];
if (the_key_info.key_states[be_byte] & be_bit) {
// Key pressed
if (amiga_code == AK_mousestuff)
togglemouse();
else
printf("Key\n");
record_key(amiga_code << 1);
} else {
// Key released
record_key((amiga_code << 1) | 1);
}
}
}
old_key_info = the_key_info;
// "Affengriff"
if ((the_key_info.key_states[0x5c >> 3] & (1 << (~0x5c & 7)))
&& (the_key_info.key_states[0x5d >> 3] & (1 << (~0x5d & 7)))
&& (the_key_info.key_states[0x5f >> 3] & (1 << (~0x5f & 7))))
MC68000_reset();
// Scroll lock toggles inhibit_frame
inhibit_frame = the_key_info.key_states[0x0f >> 3] & (1 << (~0x0f & 7));
/*
static bool ShiftState=FALSE;
if(CurentEvent->Age){
if(CurentEvent->Key==AK_LSH){
CurentEvent->Age--;
if(CurentEvent->Age==2){
if(ShiftState) {record_key((AK_LSH<<1)|1); ShiftState=FALSE; printf("ShU\n");}
else {record_key(AK_LSH<<1); ShiftState=TRUE; printf("ShD\n");}
}
}else{
CurentEvent->Age--;
if(CurentEvent->Age==2) record_key(CurentEvent->Key<<1);
if(CurentEvent->Age==0) record_key((CurentEvent->Key<<1)|1);
}
}
else{
if(CurentEvent->Next)
{
Event *TrashEvent=CurentEvent;
CurentEvent=CurentEvent->Next;
free(TrashEvent);
}
}
*/
}
// Mouse
if (window_open && inwindow) {
bitmap_window->Lock();
bitmap_view->GetMouse(&mouse_point, &mouse_buttons, FALSE);
bitmap_window->Unlock();
lastmx = mouse_point.x;
lastmy = mouse_point.y;
if(lastmx>=0&&lastmy>=0&&lastmx<hsize&&lastmy<vsize){
buttonstate[0] = mouse_buttons & B_PRIMARY_MOUSE_BUTTON;
buttonstate[1] = mouse_buttons & B_TERTIARY_MOUSE_BUTTON;
buttonstate[2] = mouse_buttons & B_SECONDARY_MOUSE_BUTTON;
}
}
}
int debuggable(void)
{
return TRUE;
}
int needmousehack(void)
{
return TRUE;
}
void LED(int on)
{
// printf("PowerLED: %d\n",on);
PowerLED->SetState((bool)~on);
}
bool LEDs[4];
void gui_led(int led, int on)
{
if(led<4)
{
LEDs[led]=on;
DriveLED->SetState(LEDs[0]|LEDs[1]|LEDs[2]|LEDs[3]);
// printf("DriveLeds: %d,%d,%d,%d\n",LEDs[0],LEDs[1],LEDs[2],LEDs[3]);
}
}
void calc_adjustment(void)
{
gfxvidinfo.x_adjust = 0;
}
void target_specific_usage(void)
{
}
int quit_program;
static void sigchldhandler(int foo)
{
}
int gui_init(void)
{
LEDs[0]=LEDs[1]=LEDs[2]=LEDs[3]=FALSE;
quit_program = 0;
return 0;
}
void gui_exit(void)
{
}
//void gui_led(int led, int on)
//{
//}
void gui_filename(int num, char *name)
{
}
static void getline(char *p)
{
}
void gui_handle_events(void)
{
}